<?php

//--------------------------------------------------------------------------------------------
//  Author: geRRy_Goo                 浮草面海               Blog: http://gumian.blog.163.com
//  Date:  2011-10-19
//--------------------------------------------------------------------------------------------
//$pid = pcntl_fork();
////这里最好不要有其他的语句   
//if ($pid == -1)
//{
//	die('could not fork');
//} else if ($pid)
//{
//	// we are the parent   
//	pcntl_wait($status); //Protect against Zombie children   
//} else
//{
//	// we are the child   
//}


//生成几个子进程抢资源，用semapher做保护
$process_num = 3;
print "老爸：我是老爸，我要生{$process_num}个小孩。\n";
$children = array();
$source_id = ftok('test.php', 'w');
$sem = sem_get($source_id, 1); //取得一个semaphore，可以申请的只有一个

/* 以下要来生小孩 */
$i = 1;
while ($i <= $process_num)
{
	$pid = pcntl_fork(); //生出一个子程序
	if ($pid == -1)
	{ //要是 $pid 是 -1 那就是出错了
		exit(1); //离开，并且报告出错
	} else if ($pid != 0)
	{  //若$pid不是0的话，那就是父进程
		/* 这是老爸专区 */
		print "老爸：生了一个第{$i}個孩子，pid是{$pid}\n";
		$children[] = $pid;
	} else
	{ //子程序拿到的 $pid 是 0
		/* 这是孩子专区 */
		break; //直接跳出
	}
	$i++;
}
if ($pid)
{
	/* 老爸会进到这里 */
	$status = null;
	print "老爸：老爸会等大家玩好才离开\n";

	foreach ($children as $pid)
	{ //要等每個孩子都离开才离开
		pcntl_waitpid($pid, $status);
		print "老爸：pid是{$pid}的那个孩子，回去时他告诉我他的状況是{$status}\n";
	}
	print '老爸也要走了' . "\n";
} else
{
	/* 以下是小朋友游乐区 */
	for ($j = 1; $j < 3; $j++)
	{
		sem_acquire($sem); //向编号为$sem信号量申请进入临界区
		/* 临界区开始 */
		print "我是第{$i}个小朋友，我是第{$j}次进入了临界区，我要玩{$j}秒\n";
		sleep($i);
		print "我是第{$i}个小朋友，要离开临界区了\n";
		/* 临界区结束 */
		sem_release($sem); //释放编号为$sem的信号量
	}
	print "我是第{$i}个小朋友，要走了\n";
}
?>